package com.netty.server.base;

import com.netty.server.handler.base.DefaultHandlerFactory;
import com.netty.server.handler.base.HandlerFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelOutboundInvoker;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;

/**
 * netty服务端启动器
 * 服务端代码参考:  https://gitee.com/takeoff/iot-modbus.git
 * https://www.jianshu.com/p/adc2de3691c7
 */
@Slf4j
public class TankServer {

    private final TankEnvironment env;

    private final HandlerFactory factory;

    public TankServer(TankEnvironment env) {
        this.env = env;
        this.factory = new DefaultHandlerFactory(env);
    }

    @Getter
    private Channel channel;

    private void init() throws InterruptedException {
        log.info("服务端启动中>>>>>>>>>>");
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(env.getBossGroup(), env.getWorkGroup())
                .channel(NioServerSocketChannel.class)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .handler(new LoggingHandler(env.getTankParams().getLogLevel()))
                .childHandler(factory.newChannelInitializer());
        channel = bootstrap.bind(env.getTankParams().getPort())
                .sync()
                .addListener(f -> log.info(String.format("服务端启动%s>>>>>>>>>>", f.isSuccess() ? "成功" : "失败")))
                .channel();
    }

    private void release() throws InterruptedException {
        log.info("服务端注销中>>>>>>>>>>");
        Optional.ofNullable(channel).ifPresent(ChannelOutboundInvoker::close);
        env.getBossGroup().shutdownGracefully().sync();
        env.getWorkGroup().shutdownGracefully().sync();
        log.info("服务端注销成功>>>>>>>>>>");
    }
}
